package com.apache.gateway.log;

import com.apache.gateway.config.HttpService;
import com.apache.tools.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.*;

/**
 * @description: 日志队列
 * @author: Hou Dayu
 * @date: Created in 2020/12/25
 */
public class OpcLogQueue {

    private static OpcLogQueue instance;
    private BlockingDeque<Map> blockingQueue;
    private Logger logger = LoggerFactory.getLogger("logs");
    private ScheduledExecutorService pools = Executors.newScheduledThreadPool(1);
    private String esUrl;

    private OpcLogQueue(){
        blockingQueue = new LinkedBlockingDeque<Map>();
        run();
    }

    public synchronized static OpcLogQueue getInstance(){
        if(null == instance){
            instance = new OpcLogQueue();
        }
        return instance;
    }

    public void setEsUrl(String esUrl) {
        this.esUrl = getESUrl(esUrl);
    }

    private String getESUrl(String esUrl) {
        String str[] = esUrl.split(",");
        int dszie = str.length;
        if(dszie > 1) {
            Random rand = new Random();
            return str[rand.nextInt(dszie)];
        } else {
            return str[0];
        }
    }

    public void add(Map auditLog) {
        try {
            blockingQueue.offerLast(auditLog,100, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            logger.error("数据加入队列出错, 消息为:{}",auditLog);
        }
    }

    //poll从队列的头部获取到信息
    public Map poll() throws InterruptedException {
        return blockingQueue.pollFirst();
    }

    private void run(){//批量写入日志，每100毫秒执行一次
        pools.scheduleWithFixedDelay(new Runnable() {
            public void run() {
                try{
                    List<Map> infos = new ArrayList();
                    int size = 0;
                    while (size < 50) {
                        Map auditLog = blockingQueue.poll();//从队列中取出一个
                        if (auditLog == null) {
                            break;
                        }
                        auditLog.put("createdTime",System.currentTimeMillis());
                        infos.add(auditLog);
                        size++;
                    }
                    if(infos.size()>0) {
                        batchMonitor(infos);
                    }
                    infos = null;
                } catch (Exception e){
                    logger.error("日志写入出错, 消息为:{}",e.getMessage());
                }
            }

            private void batchMonitor(List<Map> infos){
                String indexName = "data-warn-"+ DateUtils.Now.fmt_yyyyMM();
                if(HttpService.checkIndex(esUrl, indexName)){
                    Map<String,String> settings = new HashMap();
                    settings.put("aliases","data-warn");
                    HttpService.createIndex(esUrl,indexName,"doc",settings,getMapping());
                }
                HttpService.createBatchDoc(esUrl,indexName,"doc",infos);
            }

            private String getMapping(){
                StringBuilder sb = new StringBuilder();
                sb.append("{\"properties\" : {");
                sb.append("\"ipAddress\" : {\"type\" : \"keyword\"},");
                sb.append("\"traceId\" : {\"type\" : \"keyword\"},");
                sb.append("\"exeSys\" : {\"type\" : \"keyword\"},");
                sb.append("\"requestUrl\" : {\"type\" : \"keyword\"},");
                sb.append("\"requestTime\" : {\"type\" : \"keyword\"},");
                sb.append("\"infoType\" : {\"type\" : \"keyword\"},");
                sb.append("\"interfaceCode\" : {\"type\" : \"keyword\"},");
                sb.append("\"requestIp\" : {\"type\" : \"keyword\"},");
                sb.append("\"processingStage\" : {\"type\" : \"keyword\"},");
                sb.append("\"type\" : {\"type\" : \"keyword\"},");
                sb.append("\"rowkey\" : {\"type\" : \"keyword\"},");
                sb.append("\"requestCode\" : {\"type\" : \"keyword\"},");
                sb.append("\"processingResult\" : {\"type\" : \"keyword\"},");
                sb.append("\"exception\" : {\"type\" : \"keyword\"},");
                sb.append("\"indexDate\": {\"type\": \"date\"},");
                sb.append(",\"responseBody\" : {\"type\" : \"text\"},");
                sb.append("\"requestBody\" : {\"type\" : \"text\"},");
                sb.append("\"message\" : {\"type\" : \"text\"}");
                sb.append("}}");
                return sb.toString();
            }
        }, 0,100, TimeUnit.MILLISECONDS);
    }

}
